﻿using CRL.Cache;
using CRL.Core;
using CRL.Core.Encrypt;
using CRL.Core.Log;
using CRL.Core.Remoting;
using CRL.Core.Request;
using CRL.RedisProvider;
using CRL.RequestReport;
using Newtonsoft.Json.Linq;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace coreTest
{
    public class Program
    {
        static void Main(string[] args)
        {
            //var builder = DBConfigRegister.GetInstance();
            //builder.RegisterDBAccessBuild(dbLocation =>
            //{
            //    return new DBAccessBuild(DBType.MSSQL, "server=.;database=testDb; uid=sa;pwd=123;");
            //});
            var cb = new ConfigBuilder();
            cb.UseRedis("Server_204@127.0.0.1:6389");

            //TransConfig.RegisterTransInfoManage("test", () => new TransInfoManage());
            var asb = Assembly.GetAssembly(typeof(Program));
            var types = asb.GetTypes().Where(b => b.Namespace == typeof(Program).Namespace && b.IsPublic).ToArray();
            ConsoleTest.DoCommand(types);
            //var testAllBefor = new List<MethodInfo>();
            //testAllBefor.Add(typeof(Class1).GetMethod("config1"));
            //testAllBefor.Add(typeof(Class1).GetMethod("config2"));
            //ConsoleTest.DoCommand(new Type[] { typeof(Class1) },testAllBefor: testAllBefor);
        }
        public static void testMapper()
        {
            var item = new ProductData() { BarCode = "2222" };
            var item2 = CRL.Core.Mapper.Extensions.MapTo<ProductData2>(item);

            var list2 = new List<ProductData>() { item };
            var list3 = CRL.Core.Mapper.Extensions.MapTo<ProductData2>(list2);
            var list4 = CRL.Core.Mapper.Extensions.MapTo<ProductData, ProductData2>(list2, (a, b) =>
            {
                b.sss = a.BarCode;
            });

        }
        public static void testExport()
        {
            //SummaryAnalysisTool.SummaryAnalysis.ExportToFile("test", new Type[] { typeof(Program) }, type =>
            //  {
            //      return true;
            //      //return type.IsSubclassOf(typeof(IModel));
            //  }, type =>
            //   {
            //       //var atr = type.GetCustomAttribute<TableAttribute>();
            //       //if (atr != null)
            //       //{
            //       //    return atr.TableName;
            //       //}
            //       return type.Name;
            //   });
        }
        public static void testDelegateCache()
        {
            var val1 = "testDelegateCache";
            var data = DelegateCache.Init("test", 0.1, () =>
              {
                  System.Threading.Thread.Sleep(1000);
                  return new List<string> { val1 };
              });
            Console.WriteLine($"get {val1} return {data}");
        }
        public static void testDelegateCacheRedis()
        {
            var val1 = "testDelegateCache";
            var data = DelegateCacheFactory.GetRedisInstance().Init("test", 0.1, () =>
            {
                //throw new Exception("ssss");
                System.Threading.Thread.Sleep(1000);
                return new List<string> { val1 };
            });
            Console.WriteLine($"get {val1} return {data}");
        }
        static string getTestArgs(DateTime time)
        {
            return time.ToString();
        }
        public static void testCache5()
        {
            var val1 = "testDelegateCache2";
            var time = DateTime.Now;
            var data = DelegateCacheFactory.GetRedisInstance().InitAsyncUpdate("test22", 0.1, false, getTestArgs, time);
            Console.WriteLine($"get {val1} return {data}");
        }
        public static void testCount2()
        {
            RequestCount.Add("code1", "MSG1_R", 1);
            RequestCount.Add("code1", "MSG1_W", 2);
            RequestCount.Add("code1", "MSG2_R", 1);
            RequestCount.Add("code1", "MSG2_W", 2);

            RequestCount.Add("code2", "MSG1_R", 1);
            RequestCount.Add("code2", "MSG1_W", 2);
            RequestCount.Add("code2", "MSG2_R", 1);
            RequestCount.Add("code2", "MSG2_W", 2);

            var dic = RequestCount.GetSumByName(3600, "MSG1_R");
            var dic_ = RequestCount.GetSumByName(3600, "");
            var converted = RequestCount.ConvertDic(dic, '_');

            var dic2 = RequestCount.GetSumByType(3600, "code1");
            var dic2_ = RequestCount.GetSumByType(3600, "");
            var a = dic2.ContainsKey("MSG1_R");
            var converted2 = RequestCount.ConvertDic(dic2, '_');

        }
        static ThreadWork thread;
        public static void testContext()
        {
            thread = new ThreadWork();
            thread.Start("testThread", () =>
             {
                 CallContext.GetData<string>("name2");
                 Console.WriteLine("thread");
                 return true;
             }, 3);
        }
        public static void testThreadStop()
        {
            thread?.Stop();
        }
        public static void testRedis__()
        {
            var client = RedisClientFactory.GetCient();
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            var keys = new List<string>();
            var dic = new Dictionary<string, object>();
            for (var i = 0; i < 10; i++)
            {
                var key = $"key_{i}";
                keys.Add(key);
                //client.HSet("testAll", key, i.ToString());
                dic.Add(key, i.ToString());
            }
            for (var i = 0; i < 10; i++)
            {
                client.HSet("testAll" + i, dic);
            }
            sw.Stop();
            var el = sw.ElapsedMilliseconds;
            Console.WriteLine($"el:{el}");
            //var all = client.HGetAll<string>("testAll", keys);
        }
        public static void testRedis()
        {
            var client = RedisClientFactory.GetCient();
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            var keys = new List<string>();
            for (var i = 0; i < 100; i++)
            {
                var key = $"key_{i}";
                keys.Add(key);
                //client.HSet("testAll", key, i.ToString());
                var v = client.HGet<string>("testAll", key);
            }
            sw.Stop();
            var el = sw.ElapsedMilliseconds;
            Console.WriteLine($"el:{el}");
            //var all = client.HGetAll<string>("testAll", keys);
        }
        public static void testRedis2()
        {
            var client = RedisClientFactory.GetCient();
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            var keys = new List<string> { "testAll1", "testAll2", "testAll3", "testAll4", "testAll5", "testAll6", "testAll999" };
            var all = client.HGetAll<string>(keys);
            var all2 = client.HGet<string>("testAll1", new string[] { "key_1", "key_2", "key_3" });
            sw.Stop();
            var el = sw.ElapsedMilliseconds;
            Console.WriteLine($"el:{el}");
        }
        public static void testRedisSearchKey()
        {
            var client = new RedisClient();
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            var keys = client.SearchKey("testAll*");
            sw.Stop();
            var el = sw.ElapsedMilliseconds;
            Console.WriteLine($"el:{el}");
        }
        public static void testPolly()
        {
            var pollyKey = "test";
            var pollyData = PollyExtension.Invoke(new PollyAttribute { RetryCount = 1, RetryInterval = TimeSpan.FromSeconds(1), }, () =>
            {
                var b = 0;
                var c = 10 / b;
                return new PollyExtension.PollyData<string>() { Data = "ok" };
            }, pollyKey);
            Console.WriteLine(pollyData.Error);
        }
        public static void testQuartz()
        {
            var cronExpression = new CronExpression("* * * 4 * ?");
            var dateTime = cronExpression.GetTimeAfter(DateTime.Now).Value;
            //dateTime = dateTime.AddHours(8);
            //dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
            Console.WriteLine(dateTime.LocalDateTime);
            Console.WriteLine(dateTime.DateTime);
        }
        public static void testJosnObj()
        {
            var obj1 = new { a = 1, b = 2, c = new List<string>() };
            var obj2 = new PollyAttribute { RetryCount = 1, RetryInterval = TimeSpan.FromSeconds(1), };
            var list = new List<string> { "1", "2" };
            var jObj1 = JObject.FromObject(obj1);
            jObj1.Remove("c");
            jObj1.Add("c", JToken.FromObject(list));
            var v1 = jObj1.ToObject(obj1.GetType());
            //var jObj2 = JObject.FromObject(obj2);
        }
        static CancellationTokenSource cts;
        public static async void testCancellationToken()
        {
            cts = new CancellationTokenSource();
            Task task = Task.Delay(5000, cts.Token).ContinueWith(task =>
            {
                Console.WriteLine("任务已取消");
            });
            Console.WriteLine("按下回车键取消任务");
            Console.ReadLine();

            // 取消任务
            cts.Cancel();

            // 等待任务完成或被取消
            await task;
        }
        public static void testConcurrentControl()
        {
            for (var i = 0; i < 10; i++)
            {
                new Thread(() =>
                {
                    var a = ConcurrentControl.Check($"kk_{1}");
                    Console.WriteLine(a);
                }).Start();
            }
        }
        public static void testLog()
        {
            for (var i = 0; i < 2; i++)
            {
                new Thread((d) =>
                {
                    EventLog.Log(new LogItem { Detail = DateTime.Now.ToString() }, $"info{d}");
                }).Start(i);
            }
            EventLog.Log("testLog","ab");
            EventLog.SetLogLogWriter(new ConsoleLogWriter());
            EventLog.Error("testConsoleLog");
        }
        static RedisMessage<ProductData> client2 = null;
        public static void testRedisList()
        {
            if (client2 == null)
            {
                client2 = new RedisMessage<ProductData>();
            }
            var index = 0;

            new ThreadWork().Start("", () =>
            {
                for (var i = 0; i < 10; i++)
                {
                    index++;
                    client2.Publish(new ProductData { BarCode = index.ToString() }); ;
                }
                return true;
            }, 1);
        }
        public static void testHttpClient()
        {
            //https://www.cnblogs.com/dudu/p/csharp-httpclient-attention.html
            var urls = new string[] { "https://house.163.com", "https://news.163.com/", "https://sports.163.com/", "https://tech.163.com/game/", "https://auto.163.com/" };
            //urls = new string[] { "https://house.163.com"};
            var rand = new Random();
            var sw = new System.Diagnostics.Stopwatch();
            Dictionary<string, HttpClient> clients = new Dictionary<string, HttpClient>();

            for (var i = 0; i < 30; i++)
            {
                var index = rand.Next(0, urls.Count());
                var url = urls[index];
                HttpClient client;
                if (!clients.TryGetValue(url, out client))
                {
                    client = new HttpClient();
                    clients.Add(url, client);
                }
                var request = new ImitateWebRequest("c", httpClient: null);//TCP连接数为固定
                //var request = new ImitateWebRequest("c", httpClient: client);//TCP连接数不固定
                sw.Restart();
                var s = request.Get(url);
                sw.Stop();
                var el = sw.ElapsedMilliseconds;
                Console.WriteLine($"{DateTime.Now} {url} {el}ms");
            }
        }

        static RequestLimiter limit = new RequestLimiter(3, new TimeSpan(0, 0, 20));
        public static void testLimit()
        {
            if (limit.CheckLimit() <= 0)
            {
                Console.WriteLine("CheckLimit");
            }
            else
            {
                Console.WriteLine("ok");
            }
        }
        public static void testAes()
        {
            testAesBase("project1");
            testAesBase("projectInfo");
            testAesBase("goods");
            testAesBase("goodS");
        }
        static string testAesBase(string text)
        {
            var data = Encoding.UTF8.GetBytes(text.ToUpper());
            var key = Encoding.UTF8.GetBytes("1a3fivwe90abcdef");
            var iv = Encoding.UTF8.GetBytes("24535684");
            using AesGcm aesGcm = new AesGcm(key);
            byte[] plaintext = data;
            byte[] ciphertext = new byte[plaintext.Length];
            byte[] tag = new byte[16];
            byte[] fixedNonce = Encoding.UTF8.GetBytes("1vor567890ab");
            aesGcm.Encrypt(fixedNonce, plaintext, ciphertext, tag);
            var hex = ConvertByte(ciphertext);
            Console.WriteLine(hex);
            return hex;
        }
        const string chars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
        static string ConvertByte(byte[] data)
        {
            var len = chars2.Length;
            var charArray = data.Select(b => chars2[b % len]).ToArray();
            var str = new string(charArray);
            if (System.Text.RegularExpressions.Regex.IsMatch(str, @"^\d"))
            {
                str = "P" + str;
            }
            return str;
        }
    }
    #region obj
    /// <summary>
    /// ProductData
    /// </summary>
    public class ProductData
    {
        public string BarCode { get; set; }
        public override string ToString()
        {
            return BarCode.ToString();
        }
    }
    /// <summary>
    /// ProductData2
    /// </summary>
    public class ProductData2 : ProductData
    {
        public string sss { get; set; }
    }
    #endregion
}
